package org.gw.ylc.authorization;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;

import org.gw.ylc.base.data.EntityPermission;
import org.gw.ylc.base.data.PermissionContext;
import org.gw.ylc.base.data.PropertyAccess;
import org.gw.ylc.base.data.model.Permission;
import org.reflections.Reflections;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;

@RestController()
@RequestMapping("auth")
public class AuthCtrl {

	@RequestMapping("getMeta")
	public Object getEntityMeta(String basePackage) {
		if (basePackage == null) {
			basePackage = "";
		}
		Reflections reflections = new Reflections(basePackage);
		Set<Class<?>> set = reflections.getTypesAnnotatedWith(Entity.class);
		List<EntityMeta> r = new ArrayList<>();
		for (Class<?> clazz : set) {
			if (clazz.getPackage().getName().equals("org.gw.ylc.base.data.model")) {
				continue;
			}
			Field[] fields = clazz.getDeclaredFields();
			Stream<String> map = Arrays.asList(fields).stream().filter(f -> {
				return !Modifier.isStatic(f.getModifiers());
			}).map(f -> {
				return f.getName();
			});
			Iterator<String> iterator = map.iterator();
			List<String> list = Lists.newArrayList(iterator);
			r.add(new EntityMeta(clazz.getName(), list));
		}
		r.sort((a, b) -> {
			return a.getClassName().compareTo(b.getClassName());
		});
		return r;
	}

	@RequestMapping("getWithEntity")
	public Object getWithEntity(String entity, String role) {
		return PermissionContext.getInstance().getPermission(role, entity);
	}

	@RequestMapping("setEntityPermission")
	public Object setEntityPermission(String permission) {
		if (!StringUtils.hasText(permission)) {
			return "succ";
		}
		EntityPermission object = JSON.parseObject(permission, EntityPermission.class);
		Map<String, PropertyAccess> accessMap = object.getAccessMap();
		for (Entry<String, PropertyAccess> en : accessMap.entrySet()) {
			en.getValue().setName(en.getKey());
		}
		PermissionContext.getInstance().setPermission(object);
		return "succ";
	}

	@RequestMapping("save")
	public Object save() throws IOException {
		URI uri = URI.create(PermissionContext.getInstance().getUri());
		URI relative = uri.resolve("../../src/main/resources");
		File res = new File(relative);
		File file = new File(res, new File(uri).getName());
		file.delete();
		file.createNewFile();
		return saveToDBFile(res.getAbsolutePath());
	}

	@RequestMapping("saveToDBFile")
	public Object saveToDBFile(String file) throws IOException {
		File dbFile = new File(file);
		if (dbFile.isDirectory()) {
			dbFile = new File(dbFile, "permission");
		} else {
			System.out.println(dbFile.getAbsolutePath());
			return ("请选择文件目录");
		}
		SingleConnectionDataSource dataSource = new SingleConnectionDataSource("jdbc:h2:" + dbFile.toURI(), true);

		HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
		LocalContainerEntityManagerFactoryBean entityFactory = new LocalContainerEntityManagerFactoryBean();
		entityFactory.setJpaVendorAdapter(hibernateJpaVendorAdapter);
		entityFactory.setDataSource(dataSource);
		entityFactory.setPackagesToScan("org.gw.ylc.base.data.model");
		Properties properties = new Properties();
		properties.put("hibernate.hbm2ddl.auto", "update");
		properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
		entityFactory.setJpaProperties(properties);
		entityFactory.afterPropertiesSet();
		EntityManagerFactory object = entityFactory.getObject();
		EntityManager entityManager = object.createEntityManager();
		entityManager.setFlushMode(FlushModeType.AUTO);
		EntityTransaction transaction = entityManager.getTransaction();
		transaction.begin();
		try {
			List<EntityPermission> permissions = PermissionContext.getInstance().getPermissions();
			for (EntityPermission enp : permissions) {
				Permission permission = Permission.fromEntityPermission(enp);
				entityManager.persist(permission);
			}
			entityManager.flush();
			transaction.commit();
		} catch (Exception e) {
			transaction.rollback();
			throw e;
		} finally {
			entityManager.close();
			dataSource.destroy();
		}

		return "succ";
	}

}
